home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / aros / source / exec / memory / src / deallocate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  4.2 KB  |  179 lines

  1. /*
  2.     (C) 1995 AROS - The Amiga Replacement OS
  3.     $Id: deallocate.c 1.1 1995/11/14 22:31:07 digulla Exp digulla $
  4.     $Log: deallocate.c $
  5.  * Revision 1.1  1995/11/14  22:31:07  digulla
  6.  * Initial revision
  7.  *
  8.     Desc:
  9.     Lang: english
  10. */
  11. #include "exec_intern.h"
  12. #include "memory.h"
  13.  
  14. /*****************************************************************************
  15.  
  16.     NAME */
  17.     #include <exec/memory.h>
  18.     #include <exec/alerts.h>
  19.     #include <clib/exec_protos.h>
  20.  
  21.     __AROS_LH3(void, Deallocate,
  22.  
  23. /*  SYNOPSIS */
  24.     __AROS_LA(struct MemHeader *, freeList, A0),
  25.     __AROS_LA(APTR              , memoryBlock, A1),
  26.     __AROS_LA(unsigned long     , byteSize, D0),
  27.  
  28. /*  LOCATION */
  29.     struct ExecBase *, SysBase, 32, Exec)
  30.  
  31. /*  FUNCTION
  32.     Free block of memory associated with a given MemHandler structure.
  33.  
  34.     INPUTS
  35.     freeList    - Pointer to the MemHeader structure
  36.     memoryBlock - Pointer to the memory to be freed
  37.     byteSize    - Size of the block
  38.  
  39.     RESULT
  40.  
  41.     NOTES
  42.     The start and end borders of the block are aligned to
  43.     a multiple of sizeof(struct MemChunk) and to include the block.
  44.  
  45.     EXAMPLE
  46.  
  47.     BUGS
  48.  
  49.     SEE ALSO
  50.     Allocate()
  51.  
  52.     INTERNALS
  53.  
  54.     HISTORY
  55.     18-09-95    created by m. fleischer
  56.     15-10-95    more consistency checks added
  57.     26-10-95    digulla adjusted to new calling scheme
  58.  
  59. ******************************************************************************/
  60. {
  61.     __AROS_FUNC_INIT
  62.     struct MemChunk *p1, *p2, *p3;
  63.     UBYTE *p4;
  64.  
  65.     /* If there is no memory free nothing */
  66.     if(!byteSize)
  67.     return;
  68.  
  69.     /* Align size to the requirements */
  70.     byteSize+=(ULONG)memoryBlock&(MEMCHUNK_TOTAL-1);
  71.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  72.  
  73.     /* Align the block as well */
  74.     memoryBlock=(APTR)((ULONG)memoryBlock&~(MEMCHUNK_TOTAL-1));
  75.  
  76.     /*
  77.     The free memory list is only single linked, i.e. to insert
  78.     elements into the list I need the node as well as it's
  79.     predessor. For the first element I can use freeList->mh_First
  80.     instead of a real predessor.
  81.     */
  82.     p1=(struct MemChunk *)&freeList->mh_First;
  83.     p2=freeList->mh_First;
  84.  
  85.     /* Start and end(+1) of the block */
  86.     p3=(struct MemChunk *)memoryBlock;
  87.     p4=(UBYTE *)p3+byteSize;
  88.  
  89.     /* No chunk in list? Just insert the current one and return. */
  90.     if(p2==NULL)
  91.     {
  92.     p3->mc_Bytes=byteSize;
  93.     p3->mc_Next=NULL;
  94.     p1->mc_Next=p3;
  95.     freeList->mh_Free+=byteSize;
  96.     return;
  97.     }
  98.  
  99.     /* Follow the list to find a place where to insert our memory. */
  100.     do
  101.     {
  102. #if !defined(NO_CONSISTENCY_CHECKS)
  103.     /*
  104.         Do some constistency checks:
  105.         1. All MemChunks must be aligned to MEMCHUNK_TOTAL.
  106.         2. The end (+1) of the current MemChunk
  107.            must be lower than the start of the next one.
  108.     */
  109.     if(  ((ULONG)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  110.         ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  111.         &&p2->mc_Next!=NULL))
  112.         Alert(AN_MemCorrupt|AT_DeadEnd);
  113. #endif
  114.     /* Found a block with a higher address? */
  115.     if(p2>=p3)
  116.     {
  117. #if !defined(NO_CONSISTENCY_CHECKS)
  118.         /*
  119.         If the memory to be freed overlaps with the current
  120.         block something must be wrong.
  121.         */
  122.         if(p4>(UBYTE *)p2)
  123.         {
  124.         Alert(AN_FreeTwice);
  125.         return;
  126.         }
  127. #endif
  128.         /* End the loop with p2 non-zero */
  129.         break;
  130.     }
  131.     /* goto next block */
  132.     p1=p2;
  133.     p2=p2->mc_Next;
  134.  
  135.     /* If the loop ends with p2 zero add it at the end. */
  136.     }while(p2!=NULL);
  137.  
  138.     /* If there was a previous block merge with it. */
  139.     if(p1!=(struct MemChunk *)&freeList->mh_First)
  140.     {
  141. #if !defined(NO_CONSISTENCY_CHECKS)
  142.     /* Check if they overlap. */
  143.     if((UBYTE *)p1+p1->mc_Bytes>(UBYTE *)p3)
  144.     {
  145.         Alert(AN_FreeTwice);
  146.         return;
  147.     }
  148. #endif
  149.     /* Merge if possible */
  150.     if((UBYTE *)p1+p1->mc_Bytes==(UBYTE *)p3)
  151.         p3=p1;
  152.     else
  153.         /* Not possible to merge */
  154.         p1->mc_Next=p3;
  155.     }else
  156.     /*
  157.         There was no previous block. Just insert the memory at
  158.         the start of the list.
  159.     */
  160.     p1->mc_Next=p3;
  161.  
  162.     /* Try to merge with next block (if there is one ;-) ). */
  163.     if(p4==(UBYTE *)p2&&p2!=NULL)
  164.     {
  165.     /*
  166.        Overlap checking already done. Doing it here after
  167.        the list potentially changed would be a bad idea.
  168.     */
  169.     p4+=p2->mc_Bytes;
  170.     p2=p2->mc_Next;
  171.     }
  172.     /* relink the list and return. */
  173.     p3->mc_Next=p2;
  174.     p3->mc_Bytes=p4-(UBYTE *)p3;
  175.     freeList->mh_Free+=byteSize;
  176.     return;
  177.     __AROS_FUNC_EXIT
  178. } /* Deallocate */
  179.